package com.rzn.reading.service.impl;


import com.rzn.reading.BeanMapper;
import com.rzn.reading.BusinessException;
import com.rzn.reading.dto.PageParams;
import com.rzn.reading.dto.PageableRequestDTO;
import com.rzn.reading.entity.Attach;
import com.rzn.reading.entity.LiteratureDetail;
import com.rzn.reading.entity.Rank;
import com.rzn.reading.entity.ReadingProgress;
import com.rzn.reading.mapper.*;
import com.rzn.reading.model.dto.literature.*;
import com.rzn.reading.model.dto.readingProgress.UserReadingProgressDTO;
import com.rzn.reading.service.LiteraturedetailService;
import org.apache.commons.beanutils.BeanMap;
import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * <p>
 * 文献详细信息表 服务实现类
 * </p>
 *
 * @author rzn
 * @since 2022-02-12
 */
@Service
public class LiteraturedetailServiceImpl implements LiteraturedetailService {
    private final LiteratureDetailMapper literatureDetailMapper;
    private final AttachMapper attachMapper;
    @Autowired
    private DiscussionMapper discussionMapper;
    @Autowired
    private NoteMapper noteMapper;
    @Autowired
    private RankMapper rankMapper;
    @Autowired
    private ReadingProgressMapper readingProgressMapper;

    @Autowired
    private UserMapper userMapper;

    public LiteraturedetailServiceImpl(LiteratureDetailMapper literatureDetailMapper, AttachMapper attachMapper) {
        this.literatureDetailMapper = literatureDetailMapper;
        this.attachMapper = attachMapper;
    }

    @Transactional
    @Override
    public Boolean deleteLiterature(Integer userId, Integer literatureId) {
        LiteratureDetail literatureDetail = literatureDetailMapper.selectByPrimaryKey(literatureId);
        if (literatureDetail.getUploaderId() != userId) {
            throw new BusinessException("对不起，您不是上传者，无法删除这个文献！");
        }
        //删除所有与此文献相关信息
        discussionMapper.deleteByLiteratureId(literatureId);
        noteMapper.deleteByLiteratureId(literatureId);
        rankMapper.deleteByLiteratureId(literatureId);
        readingProgressMapper.deleteByLiteratureId(literatureId);
        attachMapper.deleteByOwner(literatureId, "literature_detail", null);
        return literatureDetailMapper.deleteByPrimaryKey(literatureId) == 1;
    }

    @Override
    public Boolean addLiterature(LiteratureCreateInputDTO literatureCreateInputDTO) {
        LiteratureDetail literatureDetail = BeanMapper.map(literatureCreateInputDTO, LiteratureDetail.class);
        int insert = literatureDetailMapper.insert(literatureDetail);
        List<Integer> file = Arrays.asList(literatureCreateInputDTO.getFileId());
        //关联附件表
        attachMapper.relateAttach(literatureDetail.getId(), "literature_detail", file);
        return insert == 1;
    }

    @Override
    public List<LiteratureItemListDTO> getLiteratureItemList(LiteratureQueryDTO literatureQueryDTO) {
        LiteratureQueryParam literatureQueryParam = BeanMapper.map(literatureQueryDTO, LiteratureQueryParam.class);
        if (literatureQueryDTO.getPage() != null && literatureQueryDTO.getPageSize() != null) {
            literatureQueryParam.setOffset((literatureQueryDTO.getPage() - 1) * literatureQueryParam.getPageSize());
        }
        List<LiteratureItemListDTO> literatureItemListDTOS = literatureDetailMapper.selectByPage(literatureQueryParam);
        List<Attach> attaches = attachMapper.selectByOwnerName("literature_detail");
        literatureItemListDTOS.forEach(literatureItemListDTO -> {
            Integer id = literatureItemListDTO.getId();
            Optional<Attach> first = attaches.stream().filter(x -> x.getOwnerId() == id).findFirst();
            if (first.isPresent()) {
                literatureItemListDTO.setUrl(first.get().getUrl());
            }
        });
        return literatureItemListDTOS;
    }

    @Override
    public List<LiteratureTypeGradeDTO> getLiteratureTypeGrade(Integer userId) {
        List<Rank> ranks = rankMapper.selectAll();
        List<LiteratureDetail> literatures = literatureDetailMapper.getLiteratureByUserId(userId);
        List<LiteratureTypeGradeDTO> literatureTypeGradeDTOS = BeanMapper.mapList(literatures, LiteratureTypeGradeDTO.class);
        List<Attach> attaches = attachMapper.selectByOwnerName("literature_detail");
        literatureTypeGradeDTOS.forEach(literatureDetail -> {
            List<Rank> list = ranks.stream().filter(x -> x.getLiteratureId() == literatureDetail.getId()).collect(Collectors.toList());
            Double avg = list.stream().map(Rank::getGrade).collect(Collectors.averagingDouble(Integer::doubleValue));
            literatureDetail.setGrade(avg);
            Optional<Attach> first = attaches.stream().filter(x -> x.getOwnerId() == literatureDetail.getId()).findFirst();
            if (first.isPresent()) {
                literatureDetail.setUrl(first.get().getUrl());
            }
        });
        return literatureTypeGradeDTOS;
    }

    @Override
    public LiteratureDetailDTO getLiteratureDetail(Integer userId, Integer literatureId) {
        Attach attach = attachMapper.selectOne("literature_detail", literatureId);
        LiteratureDetailDTO literatureDetailDTO = literatureDetailMapper.selectLiteratureDetailById(literatureId);
        ReadingProgress readingProgress = readingProgressMapper.selectByUserIdAndLiteratureId(userId, literatureId);
        UserReadingProgressDTO userReadingProgressDTO = BeanMapper.map(readingProgress, UserReadingProgressDTO.class);
        if (userReadingProgressDTO == null ) {
            userReadingProgressDTO = new UserReadingProgressDTO();
            userReadingProgressDTO.setProgress(0.0F);
        }
        literatureDetailDTO.setUserReadingProgressDTO(userReadingProgressDTO);
        if (attach != null) {
            literatureDetailDTO.setUrl(attach.getUrl());
        }
        return literatureDetailDTO;
    }

    @Override
    public Integer getAllCount() {
        Integer count = literatureDetailMapper.selectAllCount();
        return count;
    }
}
